home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
Music
/
PLAY
/
MultiPlayer
/
MultiPlayer132Src.lha
/
med8play.asm
< prev
next >
Wrap
Assembly Source File
|
1992-09-14
|
50KB
|
1,808 lines
* MultiPlayer
* Copyright (C) 1992 Bryan Ford
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* See Player.doc for info on contacting the author.
*
* Note: This playroutine was not originally written by me. In general
* these playroutines are public domain, so I am bringing the versions
* modified for MultiPlayer under the General Public License. In the
* few cases of already-copyrighted playroutines, the above copyright
* notice applies only to the parts of the file written by me.
*
* $Id: med8play.asm,v 4.2 92/07/19 16:37:38 BAF Exp Locker: BAF $
*
include "exec/types.i"
include "bry/macros.i"
include "player.i"
xdef _InitPlayer8,_RemPlayer8,_PlayModule8,_StopPlayer8,_ContModule8,_modnum8
code text
; pro8player.a
; ~~~~~~~~~~~~
; The player routine for OctaMED V1.0-3.0 5 - 8 channel songs.
; Written by Teijo Kinnunen in 1992.
;
; THIS CODE MAY BE FREELY USED AND DISTRIBUTED!
;============================================================================
AUDDEV EQU 0 ;1 = allocate channels using audio.device
CHECK EQU 1 ;1 = do range checkings (track, sample in mem etc.)
IFFMOCT EQU 1 ;1 = play IFF multi-octave samples correctly
HOLD EQU 1 ;1 = handle hold/decay
PLAYMMD0 EQU 1 ;1 = play old MMD0 modules
;============================================================================
;the MMD0 structure offsets
mmd_id EQU 0
mmd_modlen EQU 4
mmd_songinfo EQU 8
mmd_blockarr EQU 16
mmd_smplarr EQU 24
mmd_expdata EQU 32
mmd_pstate EQU 40 ; <0 = play song, 0 = don't play, >0 = play block
mmd_pblock EQU 42
mmd_pline EQU 44
mmd_pseqnum EQU 46
mmd_actplayline EQU 48
mmd_counter EQU 50
mmd_songsleft EQU 51
;the MMD0song structure
;Instrument data here (504 bytes = 63 * 8)
msng_numblocks EQU 504
msng_songlen EQU 506
msng_playseq EQU 508
msng_deftempo EQU 764
msng_playtransp EQU 766
msng_flags EQU 767
msng_flags2 EQU 768
msng_tempo2 EQU 769
msng_trkvol EQU 770
msng_mastervol EQU 786
msng_numsamples EQU 787
;Instrument data
inst_repeat EQU 0
inst_replen EQU 2
inst_midich EQU 4
inst_midipreset EQU 5
inst_svol EQU 6
inst_strans EQU 7
;Audio hardware offsets
ac_ptr EQU $00
ac_len EQU $04
ac_per EQU $06
ac_vol EQU $08
ac_end EQU $0C
ac_rest EQU $10
ac_mask EQU $14
ac_rhw EQU $16
T03SZ EQU 98
T415SZ EQU 18
;**************************************************************************
;*
;* 8 CHANNEL PLAY ROUTINE
;*
;**************************************************************************
; This code does the magic 8 channel thing (mixing).
MAGIC_8TRK MACRO
swap d6
swap d7
move.b 0(a3,d6.w),d0
add.b 0(a4,d7.w),d0
move.b d0,(a1)+
swap d6
swap d7
add.l d1,d6
add.l d2,d7
ENDM
_ChannelO8 lea trackdata8-DB(a6),a1
cmp.b #8,d0
bge.s xco8
lsl.b #2,d0
adda.w d0,a1
movea.l (a1),a1
clr.w trk_prevper(a1)
movea.l trk_audioaddr(a1),a1
clr.w ac_per(a1)
xco8 rts
_PlayNote8: ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
movea.l mmd_smplarr(a2),a0
add.w d3,d3 ;d3 = instr.num << 2
add.w d3,d3
move.l 0(a0,d3.w),d5 ;get address of instrument
IFNE CHECK
beq.s xco8
ENDC
inmem8: add.b msng_playtransp(a4),d1 ;add play transpose
add.b inst_strans(a3),d1 ;and instr. transpose
IFNE CHECK
tst.b inst_midich(a3)
bne.s xco8 ;MIDI
ENDC
clr.b trk_vibroffs(a5) ;clr vibrato offset
move.l d5,a0
subq.b #1,d1
IFNE CHECK
tst.w 4(a0)
bmi.s xco8 ;Synth
ENDC
tlwtst08: tst.b d1
bpl.s notenot2low8
add.b #12,d1 ;note was too low, octave up
bra.s tlwtst08
notenot2low8: cmp.b #62,d1
ble.s endpttest8
sub.b #12,d1 ;note was too high, octave down
endpttest8:
moveq #0,d2
moveq #0,d3
IFNE IFFMOCT
move.w 4(a0),d0 ;Soitin-struct in a0
bne.s iff5or3oct ;note # in d1 (0 - ...)
ENDC
lea _periodtable+32-DB(a6),a1
move.b trk_finetune(a5),d2 ;finetune value
add.b d2,d2
add.b d2,d2 ;multiply by 4...
ext.w d2 ;extend
movea.l 0(a1,d2.w),a1 ;period table address
move.l a1,trk_periodtbl(a5)
add.b d1,d1
move.w 0(a1,d1.w),d5 ;put period to d5
move.l a0,d0
addq.l #6,d0 ;Skip structure
move.l (a0),d1 ;length
add.l d0,d1 ;sample end pointer
move.w inst_repeat(a3),d2
move.w inst_replen(a3),d3
IFNE IFFMOCT
bra gid_setrept
gid_addtable dc.b 0,6,12,18,24,30
gid_divtable dc.b 31,7,3,15,63,127
iff5or3oct: move.l d7,-(sp)
moveq #0,d7
move.w d1,d7
divu #12,d7 ;octave #
move.l d7,d5
cmp.w #6,d7 ;if oct > 5, oct = 5
blt.s nohioct
moveq #5,d7
nohioct swap d5 ;note number in this oct (0-11) is in d5
move.l (a0),d1
cmp.w #6,d0
ble.s nounrecit
moveq #6,d0
nounrecit add.b gid_addtable-1(pc,d0.w),d7
move.b gid_divtable-1(pc,d0.w),d0
divu d0,d1 ;get length of the highest octave
swap d1
clr.w d1
swap d1
move.l d1,d0 ;d0 and d1 = length of the 1st oct
move.w inst_repeat(a3),d2
move.w inst_replen(a3),d3
moveq #0,d6
move.b shiftcnt(pc,d7.w),d6
lsl.w d6,d2
lsl.w d6,d3
lsl.w d6,d1
move.b mullencnt(pc,d7.w),d6
mulu d6,d0 ;offset of this oct from 1st oct
add.l a0,d0 ;add base address to offset
addq.l #6,d0 ;skip structure
add.l d0,d1
lea _periodtable+32-DB(a6),a1
move.b trk_finetune(a5),d6
add.b d6,d6
add.b d6,d6
ext.w d6
movea.l 0(a1,d6.w),a1
move.l a1,trk_periodtbl(a5)
add.b octstart(pc,d7.w),d5
add.b d5,d5
move.w 0(a1,d5.w),d5
move.l (sp)+,d7
bra.s gid_setrept
shiftcnt: dc.b 4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
dc.b 3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
mullencnt: dc.b 15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
dc.b 7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
octstart: dc.b 12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
dc.b 0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
ENDC
even
gid_setrept add.l d2,d2
add.l d0,d2 ;rep. start pointer
cmp.w #1,d3
bhi.s gid_noreplen2
moveq #0,d3 ;no repeat
bra.s gid_cont
gid_noreplen2 add.l d3,d3
add.l d2,d3 ;rep. end pointer
gid_cont movea.l trk_audioaddr(a5),a1 ;base of this channel's regs
move.l d0,(a1) ;put it in ac_ptr
cmp.l d0,d3
bhi.s repeat8
tst.b trk_split(a5)
beq.s pn8_nosplit0
clr.l ac_rest(a1)
subq.l #1,d1
move.l d1,ac_end(a1)
bra.s retsn18
pn8_nosplit0 sub.l d0,d1
lsr.l #1,d1
move.w d1,ac_len(a1)
move.l #_chipzero,ac_rest(a1)
move.w #1,ac_end(a1)
bra.s retsn18
repeat8: tst.b trk_split(a5)
bne.s pn8_split1
move.l d3,d1
sub.l d0,d1
lsr.l #1,d1
move.w d1,ac_len(a1)
move.l d2,ac_rest(a1) ;remember rep. start
sub.l d2,d3
lsr.l #1,d3
move.w d3,ac_end(a1) ;remember rep. length
bra.s retsn18
pn8_split1 move.l d2,ac_rest(a1)
move.l d3,ac_end(a1)
retsn18: move.w d5,ac_per(a1) ;getinsdata puts period to d5
move.w d5,trk_prevper(a5)
retsn28: rts
_IntHandler8: movem.l d2-d7/a2-a5,-(sp)
lea DB,a6
lea trksplit-DB(a6),a2
move.w currchsize2-DB(a6),d4
; ================ 8 channel handling (buffer swap) ======
move.w #800,d0
not.b whichbuff-DB(a6) ;swap buffer
bne.s usebuff1
tst.b (a2)+
beq.s tnspl0
move.l a1,$a0(a0)
move.w d4,$a4(a0)
tnspl0 lea 800(a1),a5
tst.b (a2)+
beq.s tnspl1
move.l a5,$b0(a0)
move.w d4,$b4(a0)
tnspl1 adda.w d0,a5
tst.b (a2)+
beq.s tnspl2
move.l a5,$c0(a0)
move.w d4,$c4(a0)
tnspl2 adda.w d0,a5
tst.b (a2)
beq.s buffset
move.l a5,$d0(a0)
move.w d4,$d4(a0)
bra.s buffset
usebuff1 lea 400(a1),a1
tst.b (a2)+
beq.s tnspl0b
move.l a1,$a0(a0)
move.w d4,$a4(a0)
tnspl0b lea 800(a1),a5
tst.b (a2)+
beq.s tnspl1b
move.l a5,$b0(a0)
move.w d4,$b4(a0)
tnspl1b adda.w d0,a5
tst.b (a2)+
beq.s tnspl2b
move.l a5,$c0(a0)
move.w d4,$c4(a0)
tnspl2b tst.b (a2)
beq.s buffset
adda.w d0,a5
move.l a5,$d0(a0)
move.w d4,$d4(a0)
buffset move.w #1<<7,$9c(a0)
move.l #3719168,d3 ;227 * 16384
; ============== fill buffers ============
startfillb moveq #0,d4 ;mask for DMA
lea track0hw-DB(a6),a2
tst.b trksplit-DB(a6)
bne.s tspl0c
bsr.w pushregs
bra.s tnspl0c
tspl0c bsr.s fillbuf
movea.l a5,a1
tnspl0c lea track1hw-DB(a6),a2
tst.b trksplit+1-DB(a6)
bne.s tspl1c
bsr.w pushregs
bra.s tnspl1c
tspl1c bsr.s fillbuf
movea.l a5,a1
tnspl1c lea track2hw-DB(a6),a2
tst.b trksplit+2-DB(a6)
bne.s tspl2c
bsr.w pushregs
bra.s tnspl2c
tspl2c bsr.s fillbuf
movea.l a5,a1
tnspl2c lea track3hw-DB(a6),a2
tst.b trksplit+3-DB(a6)
bne.s tspl3c
bsr.w pushregs
bra.w do_play8
tspl3c bsr.s fillbuf
bra.w do_play8
; =========================================================
;calculate channel A period
fillbuf: move.l d3,d7
move.w ac_per(a2),d6
beq.s setpzero0
move.l d7,d2
divu d6,d2
moveq #0,d1
move.w d2,d1
add.l d1,d1
add.l d1,d1
;get channel A addresses
move.l ac_end(a2),a5
move.l (a2),d0
beq.s setpzero0
chA_dfnd move.l d0,a3 ;a3 = start address, a5 = end address
;calc bytes before end
mulu currchsize-DB(a6),d2
clr.w d2
swap d2
; d2 = # of bytes/fill
add.l a3,d2 ;d2 = end position after this fill
sub.l a5,d2 ;subtract sample end
bmi.s norestart0
move.l ac_rest(a2),d0
beq.s rst0end
move.l d0,(a2)
move.l d0,a3
bra.s norestart0
rst0end clr.l (a2)
setpzero0 lea zerodata-DB(a6),a3
moveq #0,d1
norestart0
;channel B period
move.w SIZE4TRKHW+ac_per(a2),d6
beq.s setpzero0b
divu d6,d7
moveq #0,d2
move.w d7,d2
add.l d2,d2
add.l d2,d2
;channel B addresses
move.l SIZE4TRKHW+ac_end(a2),a5
move.l SIZE4TRKHW(a2),d0
beq.s setpzero0b
move.l d0,a4
mulu currchsize-DB(a6),d7
clr.w d7
swap d7
add.l a4,d7
sub.l a5,d7
bmi.s norestart0b
move.l SIZE4TRKHW+ac_rest(a2),d0
beq.s rst0endb
move.l d0,SIZE4TRKHW(a2)
move.l d0,a4
bra.s norestart0b
rst0endb clr.l SIZE4TRKHW(a2)
setpzero0b lea zerodata-DB(a6),a4
moveq #0,d2
norestart0b moveq #0,d6
moveq #0,d7
move.w currchszcnt-DB(a6),d5
lea 800(a1),a5 ;get addr. of next buffer
do8trkmagic
MAGIC_8TRK ;20 times..
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
MAGIC_8TRK
dbf d5,do8trkmagic ;do until cnt zero
end8trkmagic clr.w d6
clr.w d7
swap d6
swap d7
add.l d6,(a2)
add.l d7,SIZE4TRKHW(a2)
rts
_Wait1line: move.l d0,-(sp)
moveq #$79,d0
wl0: move.b $dff007,d1
wl1: cmp.b $dff007,d1
beq.s wl1
dbf d0,wl0
move.l (sp)+,d0
rts
; ========== this channel is not splitted
pushregs move.l ac_rhw(a2),a3 ;address of real hardware
move.w ac_per(a2),ac_per(a3) ;push new period
move.l (a2),d0 ;ac_ptr
beq.s pregs_nonewp
move.w ac_mask(a2),d1
move.w d1,$96(a0) ;stop DMA of curr. channel
or.w d1,d4
clr.l (a2)+
move.l d0,(a3)+ ;to real ac_ptr
move.w (a2),(a3) ;push ac_len
pregs_nonewp lea 400(a1),a1 ;next buffer
rts
; ========== should we start DMA of non-splitted channels?
do_play8 tst.w d4
beq.s do_play8_b ;no.
bsr.s _Wait1line
bset #15,d4
move.w d4,$96(a0)
bsr.s _Wait1line
lsr.b #1,d4
bcc.s plr_nos8dma0
move.l track0hw+ac_rest-DB(a6),$a0(a0)
move.w track0hw+ac_end-DB(a6),$a4(a0)
plr_nos8dma0 lsr.b #1,d4
bcc.s plr_nos8dma1
move.l track1hw+ac_rest-DB(a6),$b0(a0)
move.w track1hw+ac_end-DB(a6),$b4(a0)
plr_nos8dma1 lsr.b #1,d4
bcc.s plr_nos8dma2
move.l track2hw+ac_rest-DB(a6),$c0(a0)
move.w track2hw+ac_end-DB(a6),$c4(a0)
plr_nos8dma2 lsr.b #1,d4
bcc.s do_play8_b
move.l track3hw+ac_rest-DB(a6),$d0(a0)
move.w track3hw+ac_end-DB(a6),$d4(a0)
; ========== player starts here...
do_play8_b movea.l _module8-DB(a6),a2
move.l a2,d0
beq.w plr_exit8
move.l mmd_songinfo(a2),a4
moveq #0,d3
lea mmd_counter(a2),a0
move.b (a0),d3
addq.b #1,d3
cmp.b msng_tempo2(a4),d3
bge.s plr_pnewnote8 ;play new note
move.b d3,(a0)
bra.w nonewnote8 ;do just fx
; --- new note!! first get address of current block
plr_pnewnote8: clr.b (a0)
tst.w blkdelay-DB(a6)
beq.s plr_noblkdelay8
subq.w #1,blkdelay-DB(a6)
bne.w nonewnote8
plr_noblkdelay8 move.w mmd_pblock(a2),d0
movea.l mmd_blockarr(a2),a0
add.w d0,d0
add.w d0,d0
movea.l 0(a0,d0.w),a1 ;block...
move.w mmd_pline(a2),d0
IFNE PLAYMMD0
cmp.b #'1',3(a2) ;check ID type
beq.s plr_mmd1_0
move.w d0,d1
add.w d0,d0
add.w d1,d0 ;d0 = d0 * 3
clr.l numtracks-DB(a6)
move.b (a1)+,numtracks+1-DB(a6)
move.b (a1),numlines+1-DB(a6)
mulu numtracks-DB(a6),d0
pea 1(a1,d0.w)
bra.s plr_begloop
plr_mmd1_0
ENDC
add.w d0,d0
add.w d0,d0 ;d0 = d0 * 4
mulu (a1),d0 ;numtracks * d0
pea 8(a1,d0.l) ;address of the current note
move.w (a1)+,numtracks-DB(a6)
move.w (a1),numlines-DB(a6)
plr_begloop moveq #0,d7 ;number of track
moveq #0,d4
pea trackdata8-DB(a6)
plr_loop08 moveq #0,d5
cmp.w #8,d7
bge.w plr_endloop08
move.l (sp),a1
movea.l (a1)+,a5 ;get address of this track's struct
move.l a1,(sp)
; ---------------- get the note numbers
moveq #0,d3
move.l 4(sp),a1
IFNE PLAYMMD0
cmp.b #'1',3(a2)
beq.s plr_mmd1_1
move.b (a1)+,d5
move.b (a1)+,d6
move.b (a1)+,trk_cmdqual(a5)
move.b d6,d3
and.w #$0F,d6
lsr.b #4,d3
bclr #7,d5
beq.s plr_bseti4
bset #4,d3
plr_bseti4 bclr #6,d5
beq.s plr_bseti5
bset #5,d3
plr_bseti5 bra.s plr_nngok
plr_mmd1_1
ENDC
move.b (a1)+,d5 ;get the number of this note
bpl.s plr_nothinote
moveq #0,d5
plr_nothinote move.b (a1)+,d3 ;instrument number
move.b (a1)+,d6 ;cmd number
and.w #$1F,d6 ;recognize only cmds 00 - 1F
move.b (a1)+,trk_cmdqual(a5) ;databyte (qualifier)
plr_nngok move.l a1,4(sp)
; ---------------- check if there's an instrument number
and.w #$3F,d3
beq.s noinstnum8
; ---------------- finally, save the number
subq.b #1,d3
move.b d3,trk_previnstr(a5) ;remember instr. number!
IFNE HOLD
lea holdvals-DB(a6),a0
adda.w d3,a0
move.b (a0),trk_inithold(a5)
move.b 63(a0),trk_finetune(a5)
ENDC
asl.w #3,d3
lea 0(a4,d3.w),a3 ;a3 contains now address of it
move.l a3,trk_previnstra(a5)
moveq #0,d0
; ---------------- set volume to 64
movea.l trk_audioaddr(a5),a0
movea.l ac_vol(a0),a0 ;ptr to volume hardware register
moveq #64,d0
move.b d0,(a0)
move.b d0,trk_prevvol(a5)
; ---------------- remember transpose
move.b inst_strans(a3),trk_stransp(a5)
clr.w trk_soffset(a5) ;sample offset
; ---------------- check the commands
noinstnum8 move.b d6,trk_cmd(a5) ;save the effect number
beq.w fx8 ;no effect
move.b trk_cmdqual(a5),d4 ;get qualifier...
add.b d6,d6 ;* 2
move.w f_table8(pc,d6.w),d0
jmp fst8(pc,d0.w)
f_table8 dc.w fx8-fst8,fx8-fst8,fx8-fst8,f_038-fst8,fx8-fst8,fx8-fst8,fx8-fst8,fx8-fst8
dc.w f_088-fst8,f_098-fst8,fx8-fst8,f_0b8-fst8,f_0c8-fst8,fx8-fst8,fx8-fst8,f_0f8-fst8
dc.w fx8-fst8,fx8-fst8,fx8-fst8,fx8-fst8,fx8-fst8,f_158-fst8,f_168-fst8,fx8-fst8
dc.w fx8-fst8,f_198-fst8,fx8-fst8,fx8-fst8,fx8-fst8,f_1d8-fst8,fx8-fst8,f_1f8-fst8
fst8
; ---------------- tempo (F)
f_0f8 tst.b d4 ;test effect qual..
beq.s fx0fchgblck8 ;if effect qualifier (last 2 #'s)..
cmp.b #$f0,d4 ;..is zero, go to next block
bhi.s fx0fspecial8
moveq #0,d0
move.b d4,d0
bsr.w _SetTempo
bra.w fx8
; ---------------- no, it was FFx
fx0fspecial8 cmp.b #$f2,d4
bne.s isfxfe8
; ---------------- it was FF2, nothing to do now
f_1f8 move.b d5,(a5) ; save the note number
moveq #0,d5 ; clear the number for awhile
IFNE HOLD
move.b trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
bne.w plr_endloop08
st trk_noteoffcnt(a5)
ENDC
bra.w plr_endloop08
isfxfe8 cmp.b #$fe,d4
bne.s notcmdfe8
; ---------------- it was FFE, stop playing
clr.w mmd_pstate(a2)
bra.w fx8
notcmdfe8 cmp.b #$fd,d4 ;change period
bne.s isfxff8
; ---------------- FFD, change the period, don't replay the note
cmp.w #8,d7
bge.w fx8
movea.l trk_periodtbl(a5),a0 ;period table
subq.b #1,d5
bmi.w plr_endloop08 ;under zero, do nothing
add.b d5,d5
move.w 0(a0,d5.w),trk_prevper(a5) ;get & push the period
moveq #0,d5 ;don't retrigger note
bra.w fx8 ;done!!
isfxff8 cmp.b #$ff,d4 ;note off??
bne.w fx8
move.w d7,d0
bsr.w _ChannelO8
bra.w fx8
; ---------------- F00
fx0fchgblck8 move.b #1,nextblock-DB(a6)
bra.w fx8
; ---------------- change volume
f_0c8 btst #4,msng_flags(a4) ;look at flags
bne.s volhex8
move.b d4,d1 ;get again
lsr.b #4,d4 ;get number from left
mulu #10,d4 ;number of tens
and.b #$0f,d1 ;this time don't get tens
add.b d1,d4 ;add them
volhex8 cmp.b #64,d4
bhi.s go_nocmd8
movea.l trk_audioaddr(a5),a0
movea.l ac_vol(a0),a0
move.b d4,(a0)
go_nocmd8 bra.w fx8
; ---------------- tempo2 change??
f_098
IFNE CHECK
and.b #$1F,d4
bne.s fx9chk8
moveq #$20,d4
ENDC
fx9chk8 move.b d4,msng_tempo2(a4)
bra fx8
; ---------------- finetune
f_158
IFNE CHECK
cmp.b #7,d4
bgt fx8
cmp.b #-8,d4
blt fx8
ENDC
move.b d4,trk_finetune(a5)
bra fx8
; ---------------- repeat loop
f_168 tst.b d4
bne.s plr_dorpt8
move.w mmd_pline(a2),rptline-DB(a6)
bra fx8
plr_dorpt8 tst.w rptcounter-DB(a6)
beq.s plr_newrpt8
subq.w #1,rptcounter-DB(a6)
beq.s fx8
bra.s plr_setrptline8
plr_newrpt8 move.b d4,rptcounter+1-DB(a6)
plr_setrptline8 move.w rptline-DB(a6),d0
addq.w #1,d0
move.w d0,nextblockline-DB(a6)
bra.s fx8
; ---------------- note off time set??
f_088
IFNE HOLD
move.b d4,d0
and.b #$0f,d4
move.b d4,trk_inithold(a5) ;right = hold
ENDC
bra.s fx8
; ---------------- sample begin offset
f_198 tst.b d4
beq.s fx8
lsl.w #8,d4
move.w d4,trk_soffset(a5)
bra.s fx8
; ---------------- cmd Bxx, "position jump"
f_0b8
IFNE CHECK
cmp.w msng_songlen(a4),d4 ;test the song length
bhi.s fx8
ENDC
move.w d4,mmd_pseqnum(a2)
st nextblock-DB(a6)
bra.s fx8
; ---------------- cmd 1Dxx, jump to next seq, line # specified
f_1d8 move.w #$1ff,nextblock-DB(a6)
addq.w #1,d4
move.w d4,nextblockline-DB(a6)
bra.s fx8
; ---------------- try portamento (3)
f_038 subq.b #1,d5
bmi.s plr_setfx3spd8
plr_fx3note8 movea.l trk_periodtbl(a5),a0
add.b msng_playtransp(a4),d5 ;play transpose
add.b trk_stransp(a5),d5 ;and instrument transpose
bmi.s plr_endloop08 ;again.. too low
add.w d5,d5
move.w 0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
plr_setfx3spd8 tst.b d4 ;qual?
beq.s plr_endloop08 ;0 -> do nothing
move.b d4,trk_prevportspd(a5) ;remember size
bra.s plr_endloop08
; ---------------- everything is checked now: play or not to play??
fx8 tst.b d5 ;Now we'll check if we have to play a note
beq.s plr_endloop08 ;no.
; ---------------- we decided to play
move.b d5,(a5)
move.w d5,d1
moveq #0,d3
move.b trk_previnstr(a5),d3 ;instr #
movea.l trk_previnstra(a5),a3 ;instr data address
IFNE HOLD
move.b trk_inithold(a5),trk_noteoffcnt(a5)
bne.s plr_nohold8
st trk_noteoffcnt(a5)
ENDC
; ---------------- and finally:
plr_nohold8 bsr _PlayNote8
; ---------------- end of loop: handle next track, or quit
plr_endloop08 addq.b #1,d7
cmp.w numtracks-DB(a6),d7
blt.w plr_loop08
addq.l #8,sp ;trackdataptrs
lea trackdata8-DB(a6),a5
; and advance song pointers
lea nextblock-DB(a6),a3
move.w nextblockline-DB(a6),d1
beq.s plr_advlinenum
clr.w nextblockline-DB(a6)
subq.w #1,d1
bra.s plr_linenumset
plr_advlinenum move.w mmd_pline(a2),d1 ;get current line #
addq.w #1,d1 ;advance line number
plr_linenumset cmp.w numlines-DB(a6),d1 ;advance block?
bhi.s plr_chgblock ;yes.
tst.b (a3) ;command F00/1Dxx?
beq.s plr_nochgblock ;no, don't change block
plr_chgblock tst.b nxtnoclrln-DB(a6)
bne.s plr_noclrln
moveq #0,d1 ;clear line number
plr_noclrln tst.w mmd_pstate(a2) ;play block or play song
bpl.s plr_nonewseq ;play block only...
move.w mmd_pseqnum(a2),d0 ;get play sequence number
tst.b (a3)
bmi.s plr_noadvseq ;Bxx sets nextblock to -1
addq.w #1,d0 ;advance sequence number
plr_noadvseq cmp.w msng_songlen(a4),d0 ;is this the highest seq number??
blt.s plr_notagain ;no.
moveq #0,d0 ;yes: restart song
plr_notagain move.b d0,mmd_pseqnum+1(a2) ;remember new playseq-#
lea msng_playseq(a4),a0 ;offset of sequence table
move.b 0(a0,d0.w),d0 ;get number of the block
IFNE CHECK
cmp.w msng_numblocks(a4),d0 ;beyond last block??
blt.s plr_nolstblk ;no..
moveq #0,d0 ;play block 0
ENDC
plr_nolstblk move.b d0,mmd_pblock+1(a2) ;store block number
plr_nonewseq clr.w (a3) ;clear this if F00 set it
plr_nochgblock move.w d1,mmd_pline(a2) ;set new line number
IFNE HOLD
lea trackdata8-DB(a6),a5
movea.l mmd_blockarr(a2),a0
move.w mmd_pblock(a2),d0
add.w d0,d0
add.w d0,d0
movea.l 0(a0,d0.w),a1 ;block...
move.w mmd_pline(a2),d0
move.b msng_tempo2(a4),d3 ;interrupts/note
IFNE PLAYMMD0
cmp.b #'1',3(a2)
beq.s plr_mmd1_2
move.b (a1),d7 ;# of tracks
move.w d0,d1
add.w d0,d0 ;d0 * 2
add.w d1,d0 ;+ d0 = d0 * 3
mulu d7,d0
lea 2(a1,d0.w),a3
subq.b #1,d7
plr_chkholdb movea.l (a5)+,a1 ;track data
tst.b trk_noteoffcnt(a1) ;hold??
bmi.s plr_holdendb ;no.
move.b (a3),d1 ;get the 1st byte..
bne.s plr_hold1b
move.b 1(a3),d1
and.b #$f0,d1
beq.s plr_holdendb ;don't hold
bra.s plr_hold2b
plr_hold1b and.b #$3f,d1 ;note??
beq.s plr_hold2b ;no, cont hold..
move.b 1(a3),d1
and.b #$0f,d1 ;get cmd
subq.b #3,d1 ;is there command 3 (slide)
bne.s plr_holdendb ;no -> end holding
plr_hold2b add.b d3,trk_noteoffcnt(a1) ;continue holding...
plr_holdendb addq.l #3,a3 ;next note
dbf d7,plr_chkholdb
bra.s nonewnote8
plr_mmd1_2
ENDC
move.w (a1),d7 ;# of tracks
add.w d0,d0
add.w d0,d0 ;d0 = d0 * 4
mulu d7,d0
lea 8(a1,d0.l),a3
subq.b #1,d7
plr_chkhold movea.l (a5)+,a1 ;track data
tst.b trk_noteoffcnt(a1) ;hold??
bmi.s plr_holdend ;no.
move.b (a3),d1 ;get the 1st byte..
bne.s plr_hold1
move.b 1(a3),d0
and.b #$3F,d0
beq.s plr_holdend ;don't hold
bra.s plr_hold2
plr_hold1 and.b #$7f,d1 ;note??
beq.s plr_hold2 ;no, cont hold..
move.b 2(a3),d1
subq.b #3,d1 ;is there command 3 (slide)
bne.s plr_holdend ;no -> end holding
plr_hold2 add.b d3,trk_noteoffcnt(a1) ;continue holding...
plr_holdend addq.l #4,a3 ;next note
dbf d7,plr_chkhold
ENDC
nonewnote8 moveq #0,d3
move.b mmd_counter(a2),d3
plr_fxtime lea trackdata8-DB(a6),a3
moveq #0,d7 ;clear track count
plr_loop1: movea.l (a3)+,a5
cmp.w #8,d7
bge.w endl
moveq #0,d4
moveq #0,d5
moveq #0,d6
move.b trk_cmd(a5),d6 ;get the fx number
move.b trk_cmdqual(a5),d4 ;and the last 2 #'s
IFNE HOLD
tst.b trk_noteoffcnt(a5)
bmi.s plr_nofade
subq.b #1,trk_noteoffcnt(a5)
bpl.s plr_nofade
move.w d7,d0
bsr.w _ChannelO8
plr_nofade
ENDC
add.b d6,d6 ;* 2
move.w fx_table(pc,d6.w),d0
jmp fxs(pc,d0.w)
fx_table dc.w fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
dc.w fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
dc.w fx_0a-fxs,fx_xx-fxs,endl-fxs,fx_0d-fxs,fx_xx-fxs
dc.w fx_0f-fxs
dc.w fx_xx-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
dc.w fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
dc.w fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_1e-fxs
dc.w fx_1f-fxs
fxs:
; **************************************** Effect 01 ******
fx_01: tst.b d3
bne.s fx_01nocnt0
btst #5,msng_flags(a4) ;FLAG_STSLIDE??
bne endl
fx_01nocnt0 sub.w d4,trk_prevper(a5)
move.w trk_prevper(a5),d5
cmp.w #113,d5
bge plr_newper
move.w #113,d5
move.w d5,trk_prevper(a5)
bra plr_newper
; **************************************** Effect 11 ******
fx_11 tst.b d3
bne fx_xx
sub.w d4,trk_prevper(a5)
move.w trk_prevper(a5),d5
bra plr_newper
; **************************************** Effect 02 ******
fx_02: tst.b d3
bne.s fx_02nocnt0
btst #5,msng_flags(a4)
bne endl
fx_02nocnt0 add.w d4,trk_prevper(a5)
move.w trk_prevper(a5),d5
bra.w plr_newper
; **************************************** Effect 12 ******
fx_12 tst.b d3
bne fx_xx
add.w d4,trk_prevper(a5)
move.w trk_prevper(a5),d5
bra plr_newper
; **************************************** Effect 00 ******
fx_00: tst.b d4 ;both fxqualifiers are 0s: no arpeggio
beq.w fx_xx
move.l d3,d0
divu #3,d0
swap d0
tst.w d0
bne.s fx_arp12
and.b #$0f,d4
add.b (a5),d4
bra.s fx_doarp
fx_arp12: subq.b #1,d0
bne.s fx_arp2
lsr.b #4,d4
add.b (a5),d4
bra.s fx_doarp
fx_arp2: move.b (a5),d4
fx_doarp: subq.b #1,d4 ;-1 to make it 0 - 127
add.b msng_playtransp(a4),d4 ;add play transpose
add.b trk_stransp(a5),d4 ;add instrument transpose
add.b d4,d4
movea.l trk_periodtbl(a5),a1
move.w 0(a1,d4.w),d5
bra.w plr_newper
; **************************************** Effect 04 ******
fx_14 move.b #6,trk_vibshift(a5)
bra.s vib_cont
fx_04 move.b #5,trk_vibshift(a5)
vib_cont tst.b d3
bne.s nonvib
move.b d4,d1
beq.s nonvib
and.w #$0f,d1
beq.s plr_chgvibspd
move.w d1,trk_vibrsz(a5)
plr_chgvibspd: and.b #$f0,d4
beq.s nonvib
lsr.b #3,d4
and.b #$3e,d4
move.b d4,trk_vibrspd(a5)
nonvib: move.b trk_vibroffs(a5),d0
lsr.b #2,d0
and.w #$1f,d0
moveq #0,d1
move.b sinetable(pc,d0.w),d5
ext.w d5
muls trk_vibrsz(a5),d5
move.b trk_vibshift(a5),d1
asr.w d1,d5
add.w trk_prevper(a5),d5
move.b trk_vibrspd(a5),d0
add.b d0,trk_vibroffs(a5)
bra.w plr_newper
sinetable: dc.b 0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
dc.b 25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
dc.b -106,-90,-71,-49,-25,0
even
; **************************************** Effect 06 ******
fx_06: tst.b d3
bne.s fx_06nocnt0
btst #5,msng_flags(a4)
bne newvals
fx_06nocnt0 bsr.s plr_volslide ;Volume slide
bra.s nonvib ;+ Vibrato
; **************************************** Effect 07 ******
fx_07 tst.b d3
bne.s nontre
move.b d4,d1
beq.s nontre
and.w #$0f,d1
beq.s plr_chgtrespd
move.w d1,trk_tremsz(a5)
plr_chgtrespd and.b #$f0,d4
beq.s nonvib
lsr.b #2,d4
and.b #$3e,d4
move.b d4,trk_tremspd(a5)
nontre move.b trk_tremoffs(a5),d0
lsr.b #3,d0
and.w #$1f,d0
moveq #0,d1
move.b sinetable(pc,d0.w),d5
ext.w d5
muls trk_tremsz(a5),d5
asr.w #7,d5
move.b trk_tremspd(a5),d0
add.b d0,trk_tremoffs(a5)
move.b trk_prevvol(a5),d1
add.b d5,d1
bpl.s tre_pos
moveq #0,d1
tre_pos cmp.b #64,d1
ble.s tre_no2hi
moveq #64,d1
tre_no2hi move.b d1,trk_tempvol(a5)
bra.w newvals
; **************************************** Effect 0D/0A ***
fx_0a:
fx_0d: tst.b d3
bne.s fx_0dnocnt0
btst #5,msng_flags(a4)
bne newvals
fx_0dnocnt0 bsr.s plr_volslide
bra newvals
; ********* VOLUME SLIDE FUNCTION *************************
plr_volslide move.b d4,d0
moveq #0,d1
move.b trk_prevvol(a5),d1 ;move previous vol to d1
and.b #$f0,d0
bne.s crescendo
sub.b d4,d1 ;sub from prev. vol
voltest0 bpl.s novolover64
moveq #0,d1 ;volumes under zero not accepted!!!
bra.s novolover64
crescendo: lsr.b #4,d0
add.b d0,d1
voltest cmp.b #64,d1
ble.s novolover64
moveq #64,d1
novolover64 move.b d1,trk_prevvol(a5)
movea.l trk_audioaddr(a5),a0
movea.l ac_vol(a0),a0
move.b d1,(a0)
rts
; **************************************** Effect 1A ******
fx_1a tst.b d3
bne fx_xx
move.b trk_prevvol(a5),d1
add.b d4,d1
bsr.s voltest
bra newvals
; **************************************** Effect 1B ******
fx_1b tst.b d3
bne fx_xx
move.b trk_prevvol(a5),d1
sub.b d4,d1
bsr.s voltest0
bra newvals
; **************************************** Effect 05 ******
fx_05: tst.b d3
bne.s fx_05nocnt0
btst #5,msng_flags(a4)
bne newvals
fx_05nocnt0 bsr.s plr_volslide ;Volume slide
bra.s fx_03nocnt0
; **************************************** Effect 03 ******
fx_03: tst.b d3
bne.s fx_03nocnt0
btst #5,msng_flags(a4)
bne newvals
fx_03nocnt0 move.w trk_porttrgper(a5),d0 ;d0 = target period
beq.w newvals ;no target period specified
move.w trk_prevper(a5),d1 ;d1 = curr. period
move.b trk_prevportspd(a5),d4 ;get prev. speed
cmp.w d0,d1
bhi.s subper ;curr. period > target period
add.w d4,d1 ;add the period
cmp.w d0,d1
bge.s targreached
bra.s targnreach
subper: sub.w d4,d1 ;subtract
cmp.w d0,d1 ;compare current period to target period
bgt.s targnreach
targreached: move.w trk_porttrgper(a5),d1 ;eventually push target period
clr.w trk_porttrgper(a5) ;now we can forget everything
targnreach: move.w d1,trk_prevper(a5)
move.w d1,d5
bra.s plr_newper
; **************************************** Effect 13 ******
fx_13: move.w trk_prevper(a5),d5 ;this is very simple: get the old period
cmp.b #3,d3 ;and..
bge.s plr_newper ;if counter < 3
sub.w d4,d5 ;subtract effect qualifier
bra.s plr_newper
; **************************************** Effect 1E ******
fx_1e tst.w blkdelay-DB(a6)
bne.s fx_xx
addq.w #1,d4
move.w d4,blkdelay-DB(a6)
bra.s fx_xx
; **************************************** Effect 18 ******
fx_18 cmp.b d4,d3
bne fx_xx
clr.w trk_prevper(a5)
bra.s endl
; **************************************** Effect 1F ******
fx_1f move.b d4,d1
lsr.b #4,d4 ;note delay
beq.s nonotedelay
cmp.b d4,d3 ;compare to counter
blt.s fx_xx ;tick not reached
bne.s nonotedelay
bsr playfxnote ;trigger note
nonotedelay and.w #$0f,d1 ;retrig?
beq.s fx_xx
moveq #0,d0
move.b d3,d0
divu d1,d0
swap d0 ;get modulo of counter/tick
tst.w d0
bne.s fx_xx
bsr.s playfxnote ;retrigger
bra.s fx_xx
; **************************************** Effect 0F ******
fx_0f: bsr.s cmd_F
; *********************************************************
fx_xx:
newvals: move.w trk_prevper(a5),d5
plr_newper
plr_tmpper movea.l trk_audioaddr(a5),a1 ;get channel address
move.w d5,ac_per(a1) ;push period
endl: addq.b #1,d7 ;increment channel number
cmp.w numtracks-DB(a6),d7 ;all channels done???
blt.w plr_loop1 ;not yet!!!
plr_exit8 movem.l (sp)+,d2-d7/a2-a5
moveq #1,d0
rts
cmd_F cmp.b #$f1,d4
bne.s no0ff1
cmp.b #3,d3
beq.s playfxnote
rts
no0ff1: cmp.b #$f2,d4
bne.s no0ff2
cmp.b #3,d3
beq.s playfxnote
rts
no0ff2: cmp.b #$f3,d4
bne.s no0ff3
move.b d3,d0
and.b #2+4,d0 ;is 2 or 4
beq.s cF_rts
playfxnote: moveq #0,d1
move.b (a5),d1 ;get note # of previous note
beq.s cF_rts
move.b trk_noteoffcnt(a5),d0 ;get hold counter
bmi.s pfxn_nohold ;no hold, or hold over
add.b d3,d0 ;increase by counter val
bra.s pfxn_hold
pfxn_nohold move.b trk_inithold(a5),d0 ;get initial hold
bne.s pfxn_hold
st d0
pfxn_hold move.b d0,trk_noteoffcnt(a5)
move.l d3,-(sp)
moveq #0,d3
move.b trk_previnstr(a5),d3 ;and prev. sample #
move.l a3,-(sp)
movea.l trk_previnstra(a5),a3
bsr _PlayNote8
movea.l (sp)+,a3
move.l (sp)+,d3
rts
no0ff3: cmp.b #$f8,d4 ;f8 = filter off
beq.s plr_filteroff
cmp.b #$f9,d4 ;f9 = filter on
bne.s cF_rts
bclr #1,$bfe001
rts
plr_filteroff: bset #1,$bfe001
cF_rts rts
_SetTempo: move.l _module8-DB(a6),d1
beq.s ST_x
movea.l d1,a0
movea.l mmd_songinfo(a0),a0
move.w d0,msng_deftempo(a0)
tst.w d0
ble.s ST_maxszcnt
cmp.w #9,d0
bls.s ST_nodef8tempo
ST_maxszcnt moveq #10,d0
ST_nodef8tempo add.b #9,d0
move.b d0,currchszcnt-DB+1(a6)
lea eightchsizes-10-DB(a6),a0
move.b 0(a0,d0.w),d0 ;get buffersize / 2
move.w d0,currchsize2-DB(a6)
asl.w #3,d0 ;get buffersize * 4
move.w d0,currchsize-DB(a6)
ST_x rts
_Rem8chan: move.l a6,-(sp)
lea DB,a6
move.b eightrkon-DB(a6),d0
beq.s no8init
clr.b eightrkon-DB(a6)
move.w #1<<7,$dff09a
moveq #7,d0
move.l prevaud-DB(a6),d0
beq.s no8init
move.l d0,a1
move.l 4,a6
jsr -$a2(a6)
no8init move.l (sp)+,a6
rts
_End8Play: tst.b play8
beq.s noend8play
move.w #1<<7,$dff09a
move.w #$F,$dff096
clr.b play8
noend8play rts
; *************************************************************************
; *************************************************************************
; *********** P U B L I C F U N C T I O N S ***********
; *************************************************************************
; *************************************************************************
xdef _PlayModule8
xdef _InitPlayer8,_RemPlayer8,_StopPlayer8
xdef _ContModule8
; *************************************************************************
; InitModule8(a0 = module) -- extract expansion data etc.. from the module
; *************************************************************************
_InitModule8: movem.l a2-a3/d2,-(sp)
move.l a0,d0
beq.s IM_exit ;0 => xit
lea holdvals-DB(a6),a2
move.l mmd_expdata(a0),d0 ;expdata...
beq.s IM_clrhlddec ;none here
move.l d0,a1
move.l 4(a1),d0 ;exp_smp
beq.s IM_clrhlddec ;again.. nothing
move.l d0,a0 ;InstrExt...
move.w 8(a1),d2 ;# of entries
beq.s IM_clrhlddec
subq.w #1,d2 ;- 1 (for dbf)
move.w 10(a1),d0 ;entry size
IM_loop1 cmp.w #3,d0
ble.s IM_noftune
move.b 3(a0),63(a2)
IM_noftune move.b (a0),(a2)+ ;InstrExt.hold -> holdvals
adda.w d0,a0 ;ptr to next InstrExt
dbf d2,IM_loop1
bra.s IM_exit
IM_clrhlddec moveq #125,d0 ;no InstrExt => clear holdvals/decays
IM_loop2 clr.b (a2)+
dbf d0,IM_loop2
IM_exit movem.l (sp)+,a2-a3/d2
rts
; *************************************************************************
; ContModule8(a0 = module) -- continue playing
; *************************************************************************
_ContModule8 bsr.w _End8Play
moveq #0,d0
bra.s contpoint8
; *************************************************************************
; PlayModule8(a0 = module) -- init and play a module
; *************************************************************************
_PlayModule8: st d0
contpoint8 move.l a6,-(sp)
lea DB,a6
movem.l a0/d0,-(sp)
bsr _InitModule8
movem.l (sp)+,a0/d0
IFNE AUDDEV
tst.b audiodevopen-DB(a6)
beq.s PM_end ;resource allocation failure
ENDC
move.l a0,d1
beq.s PM_end ;module failure
bsr.w _End8Play
clr.l _module8-DB(a6)
move.w _modnum8,d1
beq.s PM_modfound
PM_nextmod tst.l mmd_expdata(a0)
beq.s PM_modfound
move.l mmd_expdata(a0),a1
tst.l (a1)
beq.s PM_modfound ;no more modules here!
move.l (a1),a0
subq.w #1,d1
bgt.s PM_nextmod
PM_modfound movea.l mmd_songinfo(a0),a1 ;song
move.b msng_tempo2(a1),mmd_counter(a0) ;init counter
btst #0,msng_flags(a1)
bne.s PM_filon
bset #1,$bfe001
bra.s PM_filset
PM_filon bclr #1,$bfe001
PM_filset tst.b d0
beq.s PM_noclr
clr.l mmd_pline(a0)
PM_noclr move.w mmd_pseqnum(a0),d1
add.w #msng_playseq,d1
move.b 0(a1,d1.w),d1
move.b d1,mmd_pblock+1(a0)
move.w #-1,mmd_pstate(a0)
move.l a0,_module8-DB(a6)
move.l mmd_expdata(a0),d0
beq.s PM_start
movea.l d0,a0
lea 36(a0),a0 ;track split mask
bsr.s _SetChMode
PM_start bsr.s _Start8Play
PM_end move.l (sp)+,a6
rts
_SetChMode ;a0 = address of 4 UBYTEs
movem.l a2/d2,-(sp)
lea trksplit-DB(a6),a2
lea t038+trk_split-DB(a6),a1
moveq #3,d0
moveq #0,d1
scm_loop lsr.b #1,d1
move.b (a0)+,d2
beq.s scm_split
moveq #0,d2
bra.s scm_nosplit
scm_split or.b #8,d1
st d2
scm_nosplit move.b d2,(a1)
move.b d2,4*T03SZ(a1)
lea T03SZ(a1),a1
move.b d2,(a2)+
dbf d0,scm_loop
move.w d1,chdmamask-DB(a6)
movem.l (sp)+,a2/d2
rts: rts
_Start8Play: ;d0 = pstate
lea _audiobuff,a0
move.w #1600-1,d1
clrbuffloop: clr.w (a0)+ ;clear track buffers
dbf d1,clrbuffloop
move.l _module8-DB(a6),d0
beq.s rts
move.l d0,a0
movea.l mmd_songinfo(a0),a0
move.w msng_deftempo(a0),d0 ;get deftempo
bsr.w _SetTempo
lea $dff000,a0
move.w currchsize2-DB(a6),d0
move.w d0,$a4(a0) ;set audio buffer sizes
move.w d0,$b4(a0) ;according to tempo selection
move.w d0,$c4(a0)
move.w d0,$d4(a0)
move.w #227,d1
move.w d1,$a6(a0)
move.w d1,$b6(a0)
move.w d1,$c6(a0)
move.w d1,$d6(a0)
move.l #_audiobuff,$a0(a0)
move.l #_audiobuff+800,$b0(a0)
move.l #_audiobuff+1600,$c0(a0)
move.l #_audiobuff+2400,$d0(a0)
moveq #64,d1
move.w d1,$a8(a0)
move.w d1,$b8(a0)
move.w d1,$c8(a0)
move.w d1,$d8(a0)
clr.b whichbuff-DB(a6)
movea.l 4,a1
move.w #$4000,$9a(a0)
addq.b #1,$126(a1)
lea track0hw-DB(a6),a1
moveq #7,d1
clrtrkloop clr.l (a1)
clr.w ac_per(a1)
adda.w #SIZE4TRKHW/4,a1
dbf d1,clrtrkloop
move.w #$F,$dff096 ;audio DMA off
bsr.w _Wait1line ;wait until all stopped
st play8-DB(a6)
move.w #$8080,$9a(a0)
move.w chdmamask-DB(a6),d1
bset #15,d1
move.w d1,$96(a0)
movea.l 4,a1
subq.b #1,$126(a1)
bge.s x8play
move.w #$c000,$9a(a0)
x8play rts
; *************************************************************************
; InitPlayer8() -- allocate interrupt, audio, serial port etc...
; *************************************************************************
_InitPlayer8: bsr.s _AudioInit
tst.l d0
bne.s IP_error
rts
IP_error bsr.s _RemPlayer8
moveq #-1,d0
rts
; *************************************************************************
; StopPlayer8() -- stop music
; *************************************************************************
_StopPlayer8: move.l _module8,d0
beq.s SP_nomod
movea.l d0,a0
clr.w mmd_pstate(a0)
clr.l _module8
SP_nomod bra.w _End8Play
; *************************************************************************
; RemPlayer8() -- free interrupt, audio, serial port etc..
; *************************************************************************
_RemPlayer8: bsr.s _StopPlayer8
; vvvvvvvvvvvvvvvv to _AudioRem
; *************************************************************************
_AudioRem: movem.l a5-a6,-(sp)
lea DB,a5
bsr.w _Rem8chan
IFNE AUDDEV
movea.l 4,a6
tst.b audiodevopen-DB(a5)
beq.s rem2
clr.b audiodevopen-DB(a5)
move.w #$000f,$dff096 ;stop audio DMA
; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
lea allocreq-DB(a5),a1
jsr -$1c2(a6) ;CloseDevice()
rem2: moveq #0,d0
move.b sigbitnum-DB(a5),d0
bmi.s rem3
; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
jsr -$150(a6) ;FreeSignal()
st sigbitnum-DB(a5)
ENDC
rem3: movem.l (sp)+,a5-a6
rts
_AudioInit: movem.l a4/a6/d2-d3,-(sp)
lea DB,a4
movea.l 4,a6
IFNE AUDDEV
moveq #0,d2
; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
moveq #1,d2
moveq #-1,d0
jsr -$14a(a6) ;AllocSignal()
tst.b d0
bmi.w initerr
move.b d0,sigbitnum-DB(a4)
; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
lea allocport-DB(a4),a1
move.b d0,15(a1) ;set mp_SigBit
move.l a1,-(sp)
suba.l a1,a1
jsr -$126(a6) ;FindTask(0)
move.l (sp)+,a1
move.l d0,16(a1) ;set mp_SigTask
lea reqlist-DB(a4),a0
move.l a0,(a0) ;NEWLIST begins...
addq.l #4,(a0)
clr.l 4(a0)
move.l a0,8(a0) ;NEWLIST ends...
; +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
moveq #2,d2
lea allocreq-DB(a4),a1
lea audiodevname-DB(a4),a0
moveq #0,d0
moveq #0,d1
jsr -$1bc(a6) ;OpenDevice()
tst.b d0
bne.w initerr
st.b audiodevopen-DB(a4)
ENDC
move.w #1<<7,$dff09a ;Init 8 channel stuff
moveq #7,d0 ;Audio channel 0 interrupt
lea audiointerrupt-DB(a4),a1
jsr -$a2(a6) ;SetIntVector()
move.l d0,prevaud-DB(a4)
st eightrkon-DB(a4)
moveq #0,d0
initret: movem.l (sp)+,a4/a6/d2-d3
rts
initerr: move.l d2,d0
bra.s initret
DATA __MERGED
DB: ;Data base pointer
IFNE AUDDEV
sigbitnum dc.b -1
audiodevopen dc.b 0
allocm dc.b $F,0
ENDC
chdmamask dc.w 0
trksplit dc.b 0,0,0,0
even
IFNE AUDDEV
allocport dc.l 0,0 ;succ, pred
dc.b 4,0 ;NT_MSGPORT
dc.l 0 ;name
dc.b 0,0 ;flags = PA_SIGNAL
dc.l 0 ;task
reqlist dc.l 0,0,0 ;list head, tail and tailpred
dc.b 5,0
allocreq dc.l 0,0
dc.b 0,127 ;NT_UNKNOWN, use maximum priority (127)
dc.l 0,allocport ;name, replyport
dc.w 68 ;length
dc.l 0 ;io_Device
dc.l 0 ;io_Unit
dc.w 0 ;io_Command
dc.b 0,0 ;io_Flags, io_Error
dc.w 0 ;ioa_AllocKey
dc.l allocm ;ioa_Data
dc.l 1 ;ioa_Length
dc.w 0,0,0 ;ioa_Period, Volume, Cycles
dc.w 0,0,0,0,0,0,0,0,0,0 ;ioa_WriteMsg
audiodevname dc.b 'audio.device',0
ENDC
even
zerodata dc.w 0
whichbuff dc.w 0
track0hw dc.l 0,0,$dff0a9,0,0
dc.w $0001,$df,$f0a0
track1hw dc.l 0,0,$dff0b9,0,0
dc.w $0002,$df,$f0b0
track2hw dc.l 0,0,$dff0c9,0,0
dc.w $0004,$df,$f0c0
track3hw dc.l 0,0,$dff0d9,0,0
dc.w $0008,$df,$f0d0
track4hw dc.l 0,0,$dff0a9,0,0
dc.w 0,0,0
track5hw dc.l 0,0,$dff0b9,0,0
dc.w 0,0,0
track6hw dc.l 0,0,$dff0c9,0,0
dc.w 0,0,0
track7hw dc.l 0,0,$dff0d9,0,0
dc.w 0,0,0
SIZE4TRKHW equ 4*$1A
audintname dc.b 'OctaMED AudioInterrupt',0
even
audiointerrupt dc.w 0,0,0,0,0
dc.l audintname,_audiobuff,_IntHandler8
prevaud dc.l 0
play8 dc.b 0
eightrkon dc.b 0
t038: ds.b 22
dc.l track0hw
ds.b 71
dc.b $ff
ds.b 22
dc.l track1hw
ds.b 71
dc.b $ff
ds.b 22
t238 dc.l track2hw
ds.b 71
dc.b $ff
ds.b 22
dc.l track3hw
ds.b 71
dc.b $ff
t4158 ds.b 22
dc.l track4hw
ds.b 71
dc.b $ff
ds.b 22
dc.l track5hw
ds.b 71
dc.b $ff
ds.b 22
t6158 dc.l track6hw
ds.b 71
dc.b $ff
ds.b 22
dc.l track7hw
ds.b 71
dc.b $ff
trackdata8 dc.l t038,t038+T03SZ,t038+2*T03SZ,t038+3*T03SZ
dc.l t4158,t4158+T03SZ,t4158+2*T03SZ,t4158+3*T03SZ
blkdelay dc.w 0 ;block delay (PT PatternDelay)
eightchsizes dc.b 110,120,130,140,150,160,170,180,190,200
currchsize dc.w 0 ;<< 3
currchsize2 dc.w 0
currchszcnt dc.w 0
nextblock dc.b 0 ;\ DON'T SEPARATE
nxtnoclrln dc.b 0 ;/
numtracks dc.w 0
numlines dc.w 0
nextblockline dc.w 0
rptline dc.w 0
rptcounter dc.w 0
_module8 dc.l 0
EVEN
holdvals ds.b 63
ds.b 63 ;finetune
per0 dc.w 856,808,762,720,678,640,604,570,538,508,480,453
dc.w 428,404,381,360,339,320,302,285,269,254,240,226
dc.w 214,202,190,180,170,160,151,143,135,127,120,113
dc.w 214,202,190,180,170,160,151,143,135,127,120,113
dc.w 214,202,190,180,170,160,151,143,135,127,120,113
dc.w 214,202,190,180,170,160,151,143,135,127,120,113
per1 dc.w 850,802,757,715,674,637,601,567,535,505,477,450
dc.w 425,401,379,357,337,318,300,284,268,253,239,225
dc.w 213,201,189,179,169,159,150,142,134,126,119,113
dc.w 213,201,189,179,169,159,150,142,134,126,119,113
dc.w 213,201,189,179,169,159,150,142,134,126,119,113
dc.w 213,201,189,179,169,159,150,142,134,126,119,113
per2 dc.w 844,796,752,709,670,632,597,563,532,502,474,447
dc.w 422,398,376,355,335,316,298,282,266,251,237,224
dc.w 211,199,188,177,167,158,149,141,133,125,118,112
dc.w 211,199,188,177,167,158,149,141,133,125,118,112
dc.w 211,199,188,177,167,158,149,141,133,125,118,112
dc.w 211,199,188,177,167,158,149,141,133,125,118,112
per3 dc.w 838,791,746,704,665,628,592,559,528,498,470,444
dc.w 419,395,373,352,332,314,296,280,264,249,235,222
dc.w 209,198,187,176,166,157,148,140,132,125,118,111
dc.w 209,198,187,176,166,157,148,140,132,125,118,111
dc.w 209,198,187,176,166,157,148,140,132,125,118,111
dc.w 209,198,187,176,166,157,148,140,132,125,118,111
per4 dc.w 832,785,741,699,660,623,588,555,524,495,467,441
dc.w 416,392,370,350,330,312,294,278,262,247,233,220
dc.w 208,196,185,175,165,156,147,139,131,124,117,110
dc.w 208,196,185,175,165,156,147,139,131,124,117,110
dc.w 208,196,185,175,165,156,147,139,131,124,117,110
dc.w 208,196,185,175,165,156,147,139,131,124,117,110
per5 dc.w 826,779,736,694,655,619,584,551,520,491,463,437
dc.w 413,390,368,347,328,309,292,276,260,245,232,219
dc.w 206,195,184,174,164,155,146,138,130,123,116,109
dc.w 206,195,184,174,164,155,146,138,130,123,116,109
dc.w 206,195,184,174,164,155,146,138,130,123,116,109
dc.w 206,195,184,174,164,155,146,138,130,123,116,109
per6 dc.w 820,774,730,689,651,614,580,547,516,487,460,434
dc.w 410,387,365,345,325,307,290,274,258,244,230,217
dc.w 205,193,183,172,163,154,145,137,129,122,115,109
dc.w 205,193,183,172,163,154,145,137,129,122,115,109
dc.w 205,193,183,172,163,154,145,137,129,122,115,109
dc.w 205,193,183,172,163,154,145,137,129,122,115,109
per7 dc.w 814,768,725,684,646,610,575,543,513,484,457,431
dc.w 407,384,363,342,323,305,288,272,256,242,228,216
dc.w 204,192,181,171,161,152,144,136,128,121,114,108
dc.w 204,192,181,171,161,152,144,136,128,121,114,108
dc.w 204,192,181,171,161,152,144,136,128,121,114,108
dc.w 204,192,181,171,161,152,144,136,128,121,114,108
per_8 dc.w 907,856,808,762,720,678,640,604,570,538,508,480
dc.w 453,428,404,381,360,339,320,302,285,269,254,240
dc.w 226,214,202,190,180,170,160,151,143,135,127,120
dc.w 226,214,202,190,180,170,160,151,143,135,127,120
dc.w 226,214,202,190,180,170,160,151,143,135,127,120
dc.w 226,214,202,190,180,170,160,151,143,135,127,120
per_7 dc.w 900,850,802,757,715,675,636,601,567,535,505,477
dc.w 450,425,401,379,357,337,318,300,284,268,253,238
dc.w 225,212,200,189,179,169,159,150,142,134,126,119
dc.w 225,212,200,189,179,169,159,150,142,134,126,119
dc.w 225,212,200,189,179,169,159,150,142,134,126,119
dc.w 225,212,200,189,179,169,159,150,142,134,126,119
per_6 dc.w 894,844,796,752,709,670,632,597,563,532,502,474
dc.w 447,422,398,376,355,335,316,298,282,266,251,237
dc.w 223,211,199,188,177,167,158,149,141,133,125,118
dc.w 223,211,199,188,177,167,158,149,141,133,125,118
dc.w 223,211,199,188,177,167,158,149,141,133,125,118
dc.w 223,211,199,188,177,167,158,149,141,133,125,118
per_5 dc.w 887,838,791,746,704,665,628,592,559,528,498,470
dc.w 444,419,395,373,352,332,314,296,280,264,249,235
dc.w 222,209,198,187,176,166,157,148,140,132,125,118
dc.w 222,209,198,187,176,166,157,148,140,132,125,118
dc.w 222,209,198,187,176,166,157,148,140,132,125,118
dc.w 222,209,198,187,176,166,157,148,140,132,125,118
per_4 dc.w 881,832,785,741,699,660,623,588,555,524,494,467
dc.w 441,416,392,370,350,330,312,294,278,262,247,233
dc.w 220,208,196,185,175,165,156,147,139,131,123,117
dc.w 220,208,196,185,175,165,156,147,139,131,123,117
dc.w 220,208,196,185,175,165,156,147,139,131,123,117
dc.w 220,208,196,185,175,165,156,147,139,131,123,117
per_3 dc.w 875,826,779,736,694,655,619,584,551,520,491,463
dc.w 437,413,390,368,347,328,309,292,276,260,245,232
dc.w 219,206,195,184,174,164,155,146,138,130,123,116
dc.w 219,206,195,184,174,164,155,146,138,130,123,116
dc.w 219,206,195,184,174,164,155,146,138,130,123,116
dc.w 219,206,195,184,174,164,155,146,138,130,123,116
per_2 dc.w 868,820,774,730,689,651,614,580,547,516,487,460
dc.w 434,410,387,365,345,325,307,290,274,258,244,230
dc.w 217,205,193,183,172,163,154,145,137,129,122,115
dc.w 217,205,193,183,172,163,154,145,137,129,122,115
dc.w 217,205,193,183,172,163,154,145,137,129,122,115
dc.w 217,205,193,183,172,163,154,145,137,129,122,115
per_1 dc.w 862,814,768,725,684,646,610,575,543,513,484,457
dc.w 431,407,384,363,342,323,305,288,272,256,242,228
dc.w 216,203,192,181,171,161,152,144,136,128,121,114
dc.w 216,203,192,181,171,161,152,144,136,128,121,114
dc.w 216,203,192,181,171,161,152,144,136,128,121,114
dc.w 216,203,192,181,171,161,152,144,136,128,121,114
_periodtable
dc.l per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
dc.l per1,per2,per3,per4,per5,per6,per7
bss "chip",chip
_audiobuff: ds.w 200*8
_modnum8: ds.w 1
_chipzero: ds.w 1
; the track-data structure definition:
trk_prevnote EQU 0 ;previous note number
trk_previnstr EQU 1 ;previous instrument number
trk_prevvol EQU 2 ;previous volume
trk_prevmidich EQU 3 ;previous MIDI channel
trk_cmd EQU 4 ;command (the 3rd number from right)
trk_cmdqual EQU 5 ;command qualifier (infobyte, databyte..)
trk_prevmidin EQU 6 ;previous MIDI note
trk_noteoffcnt EQU 7 ;note-off counter (hold)
trk_inithold EQU 8 ;default hold for this instrument
trk_initdecay EQU 9 ;default decay for....
trk_stransp EQU 10 ;instrument transpose
trk_finetune EQU 11 ;finetune
trk_soffset EQU 12 ;new sample offset
trk_previnstra EQU 14 ;address of the previous instrument data
trk_trackvol EQU 18
; the following data only on tracks 0 - 3
trk_prevper EQU 20 ;previous period
trk_audioaddr EQU 22 ;hardware audio channel base address
trk_sampleptr EQU 26 ;pointer to sample
trk_samplelen EQU 30 ;length (>> 1)
trk_porttrgper EQU 32 ;portamento (cmd 3) target period
trk_vibshift EQU 34 ;vibrato shift for ASR instruction
trk_vibrspd EQU 35 ;vibrato speed/size (cmd 4 qualifier)
trk_vibrsz EQU 36 ;vibrato size
trk_synthptr EQU 38 ;pointer to synthetic/hybrid instrument
trk_arpgoffs EQU 42 ;SYNTH: current arpeggio offset
trk_arpsoffs EQU 44 ;SYNTH: arpeggio restart offset
trk_volxcnt EQU 46 ;SYNTH: volume execute counter
trk_wfxcnt EQU 47 ;SYNTH: waveform execute counter
trk_volcmd EQU 48 ;SYNTH: volume command pointer
trk_wfcmd EQU 50 ;SYNTH: waveform command pointer
trk_volwait EQU 52 ;SYNTH: counter for WAI (volume list)
trk_wfwait EQU 53 ;SYNTH: counter for WAI (waveform list)
trk_synthvibspd EQU 54 ;SYNTH: vibrato speed
trk_wfchgspd EQU 56 ;SYNTH: period change
trk_perchg EQU 58 ;SYNTH: curr. period change from trk_prevper
trk_envptr EQU 60 ;SYNTH: envelope waveform pointer
trk_synvibdep EQU 64 ;SYNTH: vibrato depth
trk_synvibwf EQU 66 ;SYNTH: vibrato waveform
trk_synviboffs EQU 70 ;SYNTH: vibrato pointer
trk_initvolxspd EQU 72 ;SYNTH: volume execute speed
trk_initwfxspd EQU 73 ;SYNTH: waveform execute speed
trk_volchgspd EQU 74 ;SYNTH: volume change
trk_prevnote2 EQU 75 ;SYNTH: previous note
trk_synvol EQU 76 ;SYNTH: current volume
trk_synthtype EQU 77 ;>0 = synth, -1 = hybrid, 0 = no synth
trk_periodtbl EQU 78 ;pointer to period table
trk_prevportspd EQU 82 ;portamento (cmd 3) speed
trk_decay EQU 84 ;decay
trk_fadespd EQU 85 ;decay speed
trk_envrestart EQU 86 ;SYNTH: envelope waveform restart point
trk_envcount EQU 90 ;SYNTH: envelope counter
trk_split EQU 91 ;0 = this channel not splitted (OctaMED V2)
trk_vibroffs EQU 92 ;vibrato table offset \ DON'T SEPARATE
trk_tremoffs EQU 93 ;tremolo table offset /
trk_tremsz EQU 94 ;tremolo size
trk_tremspd EQU 96 ;tremolo speed
trk_tempvol EQU 97 ;temporary volume (for tremolo)
END